package com.denlaku.longan.service.impl;

import com.denlaku.longan.BizModule;
import com.denlaku.longan.anno.RequiredTx;
import com.denlaku.longan.anno.VarOp;
import com.denlaku.longan.qo.MyFavorQuery;
import com.denlaku.longan.qo.Query;
import com.denlaku.longan.repository.MyFavorRepository;
import com.denlaku.longan.service.DashboardService;
import com.denlaku.longan.service.MyFavorService;
import com.denlaku.longan.util.Lists;
import com.denlaku.longan.util.Objects;
import com.denlaku.longan.util.ParallelUtil;
import com.denlaku.longan.util.SnowflakeUtils;
import com.denlaku.longan.vo.Dashboard;
import com.denlaku.longan.vo.MyFavor;
import org.apache.commons.collections4.ListUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author tianx
 */
@Service
public class MyFavorServiceImpl implements MyFavorService {
    @Autowired
    private MyFavorRepository myFavorRepository;

    @Autowired
    private DashboardService dashboardService;

    @VarOp
    @Override
    @RequiredTx
    public void add(MyFavor myFavor) {
        myFavor.setId(SnowflakeUtils.nextId());
        myFavorRepository.add(myFavor);
    }

    @Override
    @RequiredTx
    public void delete(Long id) {
        myFavorRepository.delete(id);
    }

    @Override
    @RequiredTx
    public void deleteByUid(Long uid) {
        myFavorRepository.deleteByUid(uid);
    }

    @Override
    public List<MyFavor> list(MyFavorQuery query) {
        List<MyFavor> list = myFavorRepository.list(query);
        processFavors(list);
        return list;
    }

    private void processFavors(List<MyFavor> favors) {
        Map<String, List<MyFavor>> favorGroups = ListUtils.emptyIfNull(favors).stream()
                .collect(Collectors.groupingBy(MyFavor::getBiz));
        List<Runnable> tasks = Lists.ofSize(favorGroups.size());
        List<MyFavor> dashboardFavors = favorGroups.getOrDefault(BizModule.DASHBOARD, Collections.emptyList());
        tasks.add(() -> processDashboardFavors(dashboardFavors));
        ParallelUtil.execute(tasks);
    }

    private void processDashboardFavors(List<MyFavor> favors) {
        List<Runnable> tasks = Lists.ofSize(favors.size());
        for (MyFavor favor : favors) {
            tasks.add(() -> {
                Dashboard dashboard = dashboardService.get(Query.of(favor.getTenantId(), favor.getDataId()));
                favor.setTitle(Objects.map(dashboard, Dashboard::getTitle));
            });
        }
        ParallelUtil.execute(tasks);
    }

}
